package cn.edu.hnu.gpg.api;

import cn.edu.hnu.gpg.api.error.ApiError;
import cn.edu.hnu.gpg.api.error.PermissionDeniedException;
import cn.edu.hnu.gpg.api.error.UnauthenticatedException;
import cn.edu.hnu.gpg.dto.Userinfo;
import cn.edu.hnu.gpg.entity.Student;
import cn.edu.hnu.gpg.entity.Teacher;
import cn.edu.hnu.gpg.entity.User;
import cn.edu.hnu.gpg.entity.enums.UserType;
import cn.edu.hnu.gpg.service.StudentService;
import cn.edu.hnu.gpg.service.TeacherService;
import cn.edu.hnu.gpg.service.UserService;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.nio.charset.StandardCharsets;
import java.util.Base64;

@Controller
@RequestMapping("/api/auth")
public class AuthController {

    private final UserService userService;
    private final StudentService studentService;
    private final TeacherService teacherService;
    private final Logger logger = LogManager.getLogger(AuthController.class);

    @Autowired
    public AuthController(UserService userService,StudentService studentService,TeacherService teacherService) {
        this.userService = userService;
        this.studentService = studentService;
        this.teacherService = teacherService;
    }

    /**
     * 网页登录时验证用户名和密码
     * @param username 用户名
     * @param encodedPassword base64编码后的字符串
     * @throws UnauthenticatedException 验证失败时抛出
     */
    @RequestMapping(value = "login", method = RequestMethod.POST)
    @ResponseBody
    public void login(HttpServletRequest request, @RequestParam("username") String username,
                                     @RequestParam("encoded_password") String encodedPassword) throws UnauthenticatedException {

        try {
            String rawPassword = new String(Base64.getDecoder().decode(encodedPassword), StandardCharsets.UTF_8);
            if (userService.validatePassword(username, rawPassword)) {
                User user = userService.findUserByUsername(username);
                request.getSession(true).setAttribute("user", user);
            } else {
                throw new UnauthenticatedException(new ApiError(ApiError.ErrorType.ERR_INCORRECT_USERNAME_OR_PASSWORD));
            }
        } catch (RuntimeException e) {
            logger.debug(e);
            throw new UnauthenticatedException(new ApiError(ApiError.ErrorType.ERR_INCORRECT_USERNAME_OR_PASSWORD));
        }

    }

    @RequestMapping(value = "update_password", method = RequestMethod.POST)
    @ResponseBody
    public void updatePassword(HttpServletRequest request,@RequestParam("old_password") String oldPassword,
                               @RequestParam("new_password") String newPassword) throws PermissionDeniedException {
        HttpSession session = request.getSession(false);
        if (session == null)
            throw new RuntimeException("Session is null");

        String username = ((User) session.getAttribute("user")).getUsername();
        if (!userService.modifyPassword(username, oldPassword, newPassword)) {
            throw new PermissionDeniedException("Incorrect password");
        }
    }

    @RequestMapping(value = "reset_password",method = RequestMethod.POST)
    @ResponseBody
    public void resetPassword(HttpServletRequest request, @RequestBody Userinfo userinfo)throws Exception{
        String username = userinfo.getUsername(),no = userinfo.getNo();
        logger.info("username:"+username+" no:"+no);
        User user = userService.findUserByUsername(username);
        if (user == null)
            throw new IllegalArgumentException("username error");
        int id = user.getUserId();
        UserType type = user.getUserType();
        if (type == UserType.S){
            Student student = studentService.findStudentByUserId(id);
            if (student == null)
                throw new IllegalArgumentException("username not exist");
            if (!student.getStudentNumber().equals(no))
                throw new IllegalArgumentException("number error");
            if (!userService.modifyPassword(username))
                throw new IllegalArgumentException("Incorrect password");
        }
        else if (type == UserType.T){
            Teacher teacher = teacherService.findTeacherByUserId(id);
            if (teacher == null)
                throw new IllegalArgumentException("username not exist");
            if (!teacher.getTeacherNumber().equals(no))
                throw new IllegalArgumentException("number error");
            if (!userService.modifyPassword(username))
                throw new PermissionDeniedException("Incorrect password");
        }

    }
}
